﻿using ComLib;
using ComLib.ComFun;
using ComLib.ComType;
using Common;
using LogLib;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace BoardBroker
{
    public class BoardControl
    {
        #region static field and functions
        private static object _lock = new object();
        protected static BoardControl _instance;
        public static BoardControl Instance
        {
            get
            {
                return _instance;
            }
        }

        public static void CreatInstance()
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = new BoardControl();
                    }
                }
            }
        }


        /// <summary>
        /// 关闭已经存在的进程
        /// </summary>
        /// <param name="processName"></param>
        protected static void KillProcess(string processName)
        {
            Process[] processes = Process.GetProcesses();
            foreach (Process p in processes)
            {
                try
                {
                    if (p.ProcessName.Contains(processName))
                    {
                        Log.WriteAsync("MotionControl process 已经存在，中止该进程");
                        p.Kill();
                        p.WaitForExit();
                        p.Close();
                        Log.WriteAsync("进程" + p.ProcessName + "已关闭");
                    }
                }
                catch
                {

                }
            }
        }

        #endregion

        /// <summary>
        /// 代理窗口(接收来自电机控制程序窗口的同步消息)
        /// </summary>
        protected FormBoardInteraction _form = null;

        /// <summary>
        /// 代理窗口句柄
        /// </summary>
        private IntPtr _proxyWindowHandle = IntPtr.Zero;
        public IntPtr ProxyWindowHandle
        {
            get
            {
                return _proxyWindowHandle;
            }
        }

        protected int _nMsg;

        protected string _errorMessage = "";
        public string ErrorMessage
        {
            get
            {
                return _errorMessage;
            }
        }

        private BoardControl()
        {
            CreatCommunicationForm();
        }

        /// <summary>
        /// 创建用于和底层控制通信的窗口
        /// </summary>
        /// <returns></returns>
        protected void CreatCommunicationForm()
        {
            _form = new FormBoardInteraction();
            _form.Show();
            _proxyWindowHandle = _form.Handle;
            _form.RegisterEvents(OnBoardControlActionFinished);
        }

        private void StartDeviceControlProcess()
        {
            DeviceControlWindowInfo ledControl = ConfigService.Led;
            string appName = Path.GetFileNameWithoutExtension(ledControl.AppName);
            string filePath = string.Format(@"{0}\{1}\{2}", Application.StartupPath, appName, ledControl.AppName);
            if (File.Exists(filePath))
            {
                KillProcess(appName);
                ProcessStartInfo Info = new ProcessStartInfo();
                Info.FileName = filePath;
                Info.CreateNoWindow = false;
                Info.WindowStyle = ProcessWindowStyle.Minimized;
                Info.Arguments = _proxyWindowHandle.ToInt32().ToString();
                process = Process.Start(Info);
            }
            else
            {
                string logInfo = "文件不存在" + filePath;
                Log.WriteAsync(logInfo);
                MessageBox.Show(logInfo);
            }

            DeviceControlWindowInfo usbControl = ConfigService.USB;
            appName = Path.GetFileNameWithoutExtension(usbControl.AppName);
            filePath = string.Format(@"{0}\{1}\{2}", Application.StartupPath, appName, usbControl.AppName);
            if (File.Exists(filePath))
            {
                KillProcess(appName);
                ProcessStartInfo Info = new ProcessStartInfo();
                Info.FileName = filePath;
                Info.CreateNoWindow = false;
                Info.WindowStyle = ProcessWindowStyle.Minimized;
                Info.Arguments = _proxyWindowHandle.ToInt32().ToString();
                process = Process.Start(Info);
            }
            else
            {
                string logInfo = "文件不存在" + filePath;
                Log.WriteAsync(logInfo);
                MessageBox.Show(logInfo);
            }
        }


        #region SynchronizationContext fun
        protected SynchronizationContext _uiContext = null;
        protected void SendActionToMainThread(SendOrPostCallback d)
        {
            if (_uiContext != null)
            {
                _uiContext.Send(d, null);
            }
        }
        #endregion

        #region Indirect LED Control
        /// <summary>
        /// 灯光控制程序主窗口句柄
        /// </summary>
        protected IntPtr LedControlWindowHandle = IntPtr.Zero;

        /// <summary>
        /// 电机控制Demo进程
        /// </summary>
        private Process process = null;

        private WindowEmbedder Embedder = new WindowEmbedder();

        /// <summary>
        /// 电机控制Demo进程的主窗口句柄
        /// </summary>
        private IntPtr ProcessWindowHandle = IntPtr.Zero;

        /// <summary>
        ///  查找灯光控制程序的主窗口句柄: 必须在主线程中执行该动作
        /// </summary>
        /// <returns>查找是否成功</returns>
        public bool FindLedControlWindowHandle()
        {
            DeviceControlWindowInfo ledControl = ConfigService.Led;
            LedControlWindowHandle = Embedder.GetProcessMainWnd(ledControl.WindowTitle, ledControl.ClassName);
            if (LedControlWindowHandle != IntPtr.Zero)
            {
                Log.WriteAsync($"灯光控制demo窗口查找成功, 窗口句柄={LedControlWindowHandle}");
                return true;
            }
            else
            {
                _errorMessage = "灯光控制demo窗口查找失败.";
                Log.WriteAsync(_errorMessage);
                return false;
            }
        }

        private int GetLedNum(DeviceType device)
        {
            LedNumAdaptDeviceSetting setting = ConfigService.LedAdapt;
            switch (device)
            {
                case DeviceType.None:
                    return 0;
                case DeviceType.IdCardReader:
                    return setting.IdCardReader;
                case DeviceType.QrCodeScanner:
                    return setting.QrCodeScanner;
                case DeviceType.Fingerprint:
                    return setting.Fingerprint;
                case DeviceType.SignatureBoard:
                    return setting.SignatureBoard;
                case DeviceType.PaperPrinter:
                    return setting.PaperPrinter;
                default:
                    return 0;
            }
        }

        /// <summary>
        /// 发送控制灯的命令
        /// </summary>
        private void SendLedControlAction(LedControlCommand action, LEDS led = LEDS.None)
        {
            int uMsg = WindowsMessage.WM_COPYDATA;
            int wParam = (int)DeviceControlType.LedControl;
            LedActionArgs arg = new LedActionArgs();
            arg.Command = action;
            arg.LedNum = led;
            arg.SenderHandle = _proxyWindowHandle;  
            string strMsgText = JsonConvert.SerializeObject(arg);
            int nLen = Encoding.Unicode.GetBytes(strMsgText).Length;
            COPYDATASTRUCT dataStr = new COPYDATASTRUCT();
            dataStr.dwData = (IntPtr)uMsg;
            dataStr.cbData = nLen;
            dataStr.lpData = strMsgText;
            WindowsAPI.SendMessage(LedControlWindowHandle, uMsg, wParam, ref dataStr);
            Log.WriteAsync("发送亮灯控制命令:" + strMsgText);
        }

        /// <summary>
        /// 发送控制灯的命令
        /// </summary>
        private void SendLedFlashControlAction(LedControlCommand action, LEDS led, int speed, int count)
        {
            int uMsg = WindowsMessage.WM_COPYDATA;
            int wParam = (int)DeviceControlType.LedControl;
            LedActionArgs arg = new LedActionArgs();
            arg.Command = action;
            arg.LedNum = led;
            arg.Speed = speed;
            arg.Count = count;
            arg.SenderHandle = _proxyWindowHandle;

            string strMsgText = JsonConvert.SerializeObject(arg);
            int nLen = Encoding.Unicode.GetBytes(strMsgText).Length;
            COPYDATASTRUCT dataStr = new COPYDATASTRUCT();
            dataStr.dwData = (IntPtr)uMsg;
            dataStr.cbData = nLen;
            dataStr.lpData = strMsgText;
            WindowsAPI.SendMessage(LedControlWindowHandle, uMsg, wParam, ref dataStr);
            Log.WriteAsync("发送闪灯控制命令:" + strMsgText);
        }
        #endregion

        #region Indirect USB Control
    
        /// <summary>
        /// USB通断板控制程序主窗口句柄
        /// </summary>
        protected IntPtr USBControlWindowHandle = IntPtr.Zero;

        /// <summary>
        ///  查找灯光控制程序的主窗口句柄: 必须在主线程中执行该动作
        /// </summary>
        /// <returns>查找是否成功</returns>
        public bool FindUSBControlWindowHandle()
        {
            DeviceControlWindowInfo usbControl = ConfigService.USB;
            USBControlWindowHandle = Embedder.GetProcessMainWnd(usbControl.WindowTitle, usbControl.ClassName);
            if (USBControlWindowHandle != IntPtr.Zero)
            {
                Log.WriteAsync($"USB通断控制板demo窗口查找成功, 窗口句柄={USBControlWindowHandle}");
                return true;
            }
            else
            {
                _errorMessage = "USB通断控制板demo窗口查找失败.";
                Log.WriteAsync(_errorMessage);
                return false;
            }
        }

        /// <summary>
        /// 发送USB通断板控制命令
        /// </summary>
        private void SendUSBControlAction(USBControlCommand action, int channel=0)
        {
            int uMsg = WindowsMessage.WM_COPYDATA;
            int wParam = (int)DeviceControlType.USBControl;
            USBControlCommandArgs args = new USBControlCommandArgs();
            args.Command = action;
            args.Channel = channel;
            args.SenderHandle = _proxyWindowHandle;
            string strMsgText = JsonConvert.SerializeObject(args);
            int nLen = Encoding.Unicode.GetBytes(strMsgText).Length;
            COPYDATASTRUCT dataStr = new COPYDATASTRUCT();
            dataStr.dwData = (IntPtr)uMsg;
            dataStr.cbData = nLen;
            dataStr.lpData = strMsgText;
            WindowsAPI.SendMessage(USBControlWindowHandle, uMsg, wParam, ref dataStr);
            Log.WriteAsync("发送USB通断控制命令:" + strMsgText);
        }     
        #endregion

        #region Motion Control Function
        /// <summary>
        /// 等待处理事件
        /// </summary>
        protected ManualResetEventSlim _mres = new ManualResetEventSlim(false);

        // 工作流程是否开始
        protected bool _bWorkStarting = false;
        public bool IsRunning
        {
            get { return _bWorkStarting; }
        }
      
        public event USBControlCommandSendDelegate CommandSend;
        protected void OnUSBControlCommondSend(USBControlCommand m)
        {
            if (CommandSend != null)
            {
                CommandSend(m);
            }
        }

        /// <summary>
        /// 初始化设备
        /// </summary>
        /// <returns></returns>
        public void InitDevice()
        {
            Log.AddBeginningBoundary();

            Log.WriteAsync("执行初始化灯光控制设备...");
            SendLedControlAction(LedControlCommand.Init);

            Log.WriteAsync("执行初始化USB通断控制设备...");
            SendUSBControlAction(USBControlCommand.Init);
        }

        /// <summary>
        /// 关闭设备
        /// </summary>
        /// <returns></returns>
        public void CloseDevice()
        {
            Log.WriteAsync("关闭灯光控制设备...");
            SendLedControlAction(LedControlCommand.Exit);

            Log.WriteAsync("关闭USB通断控制设备...");
            SendUSBControlAction(USBControlCommand.Exit);
            Log.AddEndingBoundary();          
        }

        public void StartWorking()
        {
            if(!_bWorkStarting)
            {
                _bWorkStarting = true;
                TurnOnLight(LEDS.LED1);
                Thread.Sleep(100);
                TurnOnLight(LEDS.LED2);
                Thread.Sleep(100);
                TurnOnLight(LEDS.LED3);
            }         
        }

        public void StopWorking()
        {
            if (_bWorkStarting)
            {
                _bWorkStarting = false;
                TurnOffLight(LEDS.LED1);
                Thread.Sleep(100);
                TurnOffLight(LEDS.LED2);
                Thread.Sleep(100);
                TurnOffLight(LEDS.LED3);
            }
        }

        public void TurnOnLight(LEDS led)
        {
            SendLedControlAction(LedControlCommand.SetLightOn, led);
        }

        public void TurnOffLight(LEDS led)
        {
            SendLedControlAction(LedControlCommand.SetLightOff, led);
        }

        public void SetLightFlash(LEDS led, int rate, int cnt)
        {
            SendLedFlashControlAction(LedControlCommand.SetLedFlash, led, rate, cnt);
        }

        private void OnBoardControlActionFinished(object sender, USBControlActionFinishedEventArgs e)
        {
            string strLog = "";
            USB_CONTROL_ACTION_STATUS state = e.State;
            switch (state)
            {
                case USB_CONTROL_ACTION_STATUS.Done:
                    strLog = $"USB通断控制动作{e.Command}执行成功";
                    break;
                case USB_CONTROL_ACTION_STATUS.Failed:
                    strLog = $"USB通断控制动作{e.Command}执行失败";
                    break;
                default:
                    break;
            }           
            if (strLog != string.Empty)
            {
                Log.WriteAsync(strLog);
            }
        }
        #endregion
    }
}
